#include <sys/time.h>

static int s_timer_count = 0;

static TimerObject* _NewTimerObject() {
    TimerObject *obj = (TimerObject*)malloc(sizeof(TimerObject));
    memset(obj, 0, sizeof(TimerObject));
    ++ s_timer_count;
    return obj;
}

static void _DeleteTimerObject(TimerObject *timer) {
    -- s_timer_count;
    free(timer);
}

static uint32_t _GetNowMs() {
    struct timeval tv = {0, 0};
    gettimeofday(&tv, NULL);
    uint32_t now = ((tv.tv_sec * 1000) + (tv.tv_usec / 1000));
    return now;
}

static uint32_t _GetWaitTimeMs(struct list_head *head) {
    if (list_empty(head))
        return FOREVER_TIME_MS;

    uint32_t now_ms = _GetNowMs();
    //! 取第一个节点的执行时间就可以了
    TimerObject *timer = (TimerObject*)list_entry(head->next, TimerObject, list_node);
    if (timer->execute_time_ms < now_ms)
        return 0;

    return timer->execute_time_ms - now_ms;
}

/**
 * 将定时器根据execute_time_ms由小到大插入到链表中
 *
 * \param head          - 链表头
 * \param timer_info    - 定时器对象
 *
 * \return  bool        - 是否插入到队列头
 */
static bool _InsertToTimerList(struct list_head *head, TimerObject *new_timer) {
    if (list_empty(head)) {
        list_add(&new_timer->list_node, head);
        return true;
    }

    struct list_head *pos = NULL;
    bool is_insert_front = true;
    bool is_inserted = false;

    list_for_each(pos, head) {
        TimerObject* this_timer = (TimerObject*)list_entry(pos, TimerObject, list_node);
        if (this_timer->execute_time_ms > new_timer->execute_time_ms) {
            list_add_tail(&new_timer->list_node, pos);
            is_inserted = true;
            break;
        }
        is_insert_front = false;
    }

    if (!is_inserted)
        list_add_tail(&new_timer->list_node, head);

    return is_insert_front;
}

static TimerObject* _RemoveFromTimerList(struct list_head *head, int timer_id) {
    struct list_head *pos = NULL;
    list_for_each(pos, head) {
        TimerObject* this_timer = (TimerObject*)list_entry(pos, TimerObject, list_node);
        if (this_timer->timer_id == timer_id) {
            list_del(pos);
            return this_timer;
        }
    }
    return NULL;
}

static void _DeleteAllTimerList(struct list_head *head) {
    while (!list_empty(head)) {
        struct list_head *first_pos = head->next;
        TimerObject *timer = (TimerObject*)list_entry(first_pos, TimerObject, list_node);
        list_del(first_pos);
        _DeleteTimerObject(timer);
    }
}

#ifdef DEBUG
static void _PrintTimerList(struct list_head *head) {
    struct list_head *pos = NULL;
    list_for_each(pos, head) {
        TimerObject* this_timer = (TimerObject*)list_entry(pos, TimerObject, list_node);
            printf("> timer_id:%d, time:%u, interval:%u\n",
                   this_timer->timer_id,
                   this_timer->execute_time_ms,
                   this_timer->interval_ms);
    }
}
#endif

static UEventRetCode _CheckTimerAfterWait(UEventLoop *loop) {
    uint32_t now_ms = _GetNowMs();

    loop->executing_timer_callback = true;
    while (!list_empty(&loop->timer_list)) {
        struct list_head *first = loop->timer_list.next;
        TimerObject *timer_info = list_entry(first, TimerObject, list_node);
        if (timer_info->execute_time_ms <= now_ms) {    //! 说明定时已经到了
            list_del(first);
            UEventTimerDetail *detail = &timer_info->detail;
            (detail->callback_func)(timer_info->timer_id, detail->callback_arg);

            if (timer_info->interval_ms > 0) {  //! 这个定时器是周期性定时
                timer_info->execute_time_ms += timer_info->interval_ms;
                _InsertToTimerList(&loop->timer_list, timer_info);
            } else {
                _DeleteTimerObject(timer_info);
            }
        } else {
            break;  //! 后面的定时器都还没有到时间
        }
    }
    loop->executing_timer_callback = false;

#ifdef DEBUG
    _PrintTimerList(&loop->timer_list);
#endif

    return kUEventOK;
}

static UEventRetCode _AddTimer(UEventLoop *loop, int timer_id, uint32_t execute_time_ms, uint32_t interval_ms, const UEventTimerDetail *detail) {
    TimerObject* timer = _RemoveFromTimerList(&loop->timer_list, timer_id);
    if (timer == NULL) {    //! 为空表示之前没有这个定时器
        timer = _NewTimerObject();
        timer->timer_id = timer_id;
    }

    timer->execute_time_ms = execute_time_ms;
    timer->interval_ms = interval_ms;
    memcpy(&timer->detail, detail, sizeof(UEventTimerDetail));

    if (_InsertToTimerList(&loop->timer_list, timer))
        _Wakeup(loop);

    return kUEventOK;
}

UEventRetCode UEvent_RunAt(UEventLoop *loop, int timer_id, uint32_t execute_time_ms, const UEventTimerDetail *detail) {
    if (loop == NULL || timer_id < 0 || detail == NULL)
        return kUEventInvalidArgument;

    if (execute_time_ms < _GetNowMs())    //! 由于不清楚用户传的时间是否有效，所以必须要检查
        return kUEventExecuteTimeExpired;

    return _AddTimer(loop, timer_id, execute_time_ms, 0, detail);
}

UEventRetCode UEvent_RunAfter(UEventLoop *loop, int timer_id, uint16_t wait_time_ms, const UEventTimerDetail *detail) {
    if (loop == NULL || timer_id < 0 || detail == NULL)
        return kUEventInvalidArgument;

    return _AddTimer(loop, timer_id, _GetNowMs() + wait_time_ms, 0, detail);
}

UEventRetCode UEvent_RunEvery(UEventLoop *loop, int timer_id, uint32_t interval_ms, const UEventTimerDetail *detail) {
    if (loop == NULL || timer_id < 0 || interval_ms == 0 || detail == NULL)
        return kUEventInvalidArgument;

    return _AddTimer(loop, timer_id, _GetNowMs() + interval_ms, interval_ms, detail);
}

UEventRetCode UEvent_RunTimer(UEventLoop *loop, int timer_id, uint32_t wait_time_ms, uint32_t interval_ms, const UEventTimerDetail *detail) {
    if (loop == NULL || timer_id < 0 || (wait_time_ms == 0 && interval_ms == 0) || detail == NULL)
        return kUEventInvalidArgument;

    return _AddTimer(loop, timer_id, _GetNowMs() + wait_time_ms, interval_ms, detail);
}

UEventRetCode UEvent_StopTimer(UEventLoop *loop, int timer_id) {
    TimerObject *timer = _RemoveFromTimerList(&loop->timer_list, timer_id);
    if (timer != NULL) {
        _DeleteTimerObject(timer);
    }
    return kUEventOK;
}
